# _*_ encoding:utf-8 _*_
import json
import re

from django.shortcuts import render
from django.views import View
from django.http import JsonResponse
from django.contrib.auth import login

from QQLoginTool.QQtool import OAuthQQ
from django_redis import get_redis_connection

from meiduo_mall.utils.configer import ConfigObj
from oauth.models import OAuthQQUser
from meiduo_mall.utils.secret import SecretOauth
from users.models import User


class QQURLView(View):

    def get(self, request):

        # 1. 提取参数
        next = request.GET.get('next')
        # 2. 校验参数
        # 3. 业务数据处理  -->  获取登录页面url
        oauth = OAuthQQ(client_id=ConfigObj.get('config', 'QQ_CLIENT_ID'),  # appid
                        client_secret=ConfigObj.get('config', 'QQ_CLIENT_SECRET'),  # appkey
                        redirect_uri=ConfigObj.get('config', 'QQ_REDIRECT_URI'),  # 回调页面地址
                        state=next)  # 额外的参数，在三方交互中全程携带，通常使用该参数来指定用户登录成功之后跳转的用户页面

        login_url = oauth.get_qq_url()

        # 4. 构建响应
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'login_url': login_url}, json_dumps_params={'ensure_ascii': False})


class QQUserView(View):

    # QQ登录接口2
    def get(self, request):
        # 1. 提取参数
        code = request.GET.get('code')

        # 2. 校验参数
        if code is None:
            return JsonResponse({'code': 400, 'errmsg': '缺少必要参数'}, json_dumps_params={'ensure_ascii': False})

        # 3. 业务数据处理（业务性校验） --> 获取openid
        # TODO: 获取用户QQ身份（openid）
        # 3.1 获取oauthQQ对象
        oauth = OAuthQQ(client_id=ConfigObj.get('config', 'QQ_CLIENT_ID'),  # appid
                        client_secret=ConfigObj.get('config', 'QQ_CLIENT_SECRET'),  # appkey
                        redirect_uri=ConfigObj.get('config', 'QQ_REDIRECT_URI'),  # 回调页面地址
                        state=next)  # 额外的参数，在三方交互中全程携带，通常使用该参数来指定用户登录成功之后跳转的用户页面


        try:
            # 3.2 校验code, 获取Access Token
            access_token = oauth.get_access_token(code)

            # 3.3 根据Access Token 获取openid
            openid = oauth.get_open_id(access_token)
        except BaseException as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': 'QQ身份验证有误'}, json_dumps_params={'ensure_ascii': False})

        # TODO： 判断用户是否绑定账号
        try:
            oauth_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist as e:
            # 未绑定 ---> 加密openid返回给前端（前端跳转到绑定页面）
            access_token = SecretOauth().dumps({"openid": openid})
            return JsonResponse({'code': 1, 'errmsg': 'ok', 'access_token': access_token}, json_dumps_params={'ensure_ascii': False})
        else:
            # 已绑定 ---> 直接正常响应  ---> 登录成功
            # 状态保持  oauth_user.user 是外键关联字段，关联的是User模型类对象
            user = oauth_user.user
            login(request, user)
            response = JsonResponse({'code': 0, 'errmsg': 'ok'}, json_dumps_params={'ensure_ascii': False})
            response.set_cookie('username', user.username, max_age=3600 * 24 * 14)

            # TODO: 合并购物车
            from carts.utils import merge_cart_cookie_to_redis
            merge_cart_cookie_to_redis(request, response)

            return response

    # QQ登录接口3
    def post(self, request):
        # 1. 提取参数
        data = json.loads(request.body.decode())
        mobile = data.get('mobile')
        password = data.get('password')
        sms_code = data.get('sms_code')
        access_token = data.get('access_token')  # 加密的字典
        print(access_token)

        # 2. 校验参数
        # 2.1 必要性校验
        if not all([mobile, password, sms_code, access_token]):
            return JsonResponse({'code': 400, 'errmsg': '缺少必要参数'}, json_dumps_params={'ensure_ascii': False})

        # 2.2 约束性校验
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400, 'errmsg': '请输入正确的手机号码'}, json_dumps_params={'ensure_ascii': False})

        # 判断密码是否合格
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return JsonResponse({'code': 400, 'errmsg': '请输入8-20位的密码'}, json_dumps_params={'ensure_ascii': False})

        # 2.3 业务性校验
        conn = get_redis_connection('verify_code')
        sms_code_from_redis = conn.get(f'sms_{mobile}')
        if not sms_code_from_redis:
            return JsonResponse({'code': 400, 'errmsg': '短信验证码过期'}, status=400, json_dumps_params={'ensure_ascii': False})

        if sms_code.lower() != sms_code_from_redis.decode().lower():
            return JsonResponse({'code': 400, 'errmsg': '短信验证码输入错误'}, status=400, json_dumps_params={'ensure_ascii': False})

        # 3. 业务数据处理：绑定帐号
        # 3.1 解密openid
        data_dice = SecretOauth().loads(access_token)
        if not data_dice:
            return JsonResponse({'code': 400, 'errmsg': 'openid有误'}, json_dumps_params={'ensure_ascii': False})

        openid = data_dice.get('openid')

        # 3.2 根据用户传递的手机号查找用户对象
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist as e:
            # 未注册美多帐号  --->  新建绑定
            user = User.objects.create_user(
                username=mobile,
                mobile=mobile,
                password=password
            )

        else:
            # 注册过帐号 --> 直接绑定
            if not user.check_password(password):
                return JsonResponse({'code': 400, 'errmsg': '密码错误'}, json_dumps_params={'ensure_ascii': False})

        # 绑定
        OAuthQQUser.objects.create(user=user, openid=openid)

        # 4. 构建响应
        login(request, user)
        response = JsonResponse({'code': 0, 'errmsg': 'ok'}, json_dumps_params={'ensure_ascii': False})
        response.set_cookie('username', user.username, max_age=3600 * 24 * 14)

        # TODO: 合并购物车
        from carts.utils import merge_cart_cookie_to_redis
        merge_cart_cookie_to_redis(request, response)

        return response









